package org.biloxi.commands.impl;

import org.biloxi.commands.Command;
import org.biloxi.commands.CommandRepository;
import org.biloxi.commands.changephase.ChangePhase;
import org.biloxi.commands.changephase.events.PhaseEvent;
import org.biloxi.commands.changeturn.ChangeTurn;
import org.biloxi.commands.draw.Draw;
import org.biloxi.commands.endgame.EndGame;
import org.biloxi.commands.movecard.MoveCard;
import org.biloxi.commands.playcard.PlayCard;
import org.biloxi.commands.playerlost.PlayerLost;
import org.biloxi.game.Game;
import org.biloxi.model.GameState.Phase;
import org.biloxi.player.PlayerID;
import org.biloxi.player.actions.ActionOptionPair;

public class CommandRepositoryImpl implements CommandRepository {

	public final Game _game;

	public final Command<ChangePhase.Options, ChangePhase.Result> _changePhase = new ChangePhase(this);
	public final Command<ChangeTurn.Options, ChangeTurn.Result> _changeTurn = new ChangeTurn(this);
	public final Command<Draw.Options, Draw.Result> _draw = new Draw(this);
	public final Command<EndGame.Options, EndGame.Result> _endGame = new EndGame(this);
	public final Command<MoveCard.Options, MoveCard.Result> _moveCard = new MoveCard(this);
	public final Command<PlayCard.Options, PlayCard.Result> _playCard = new PlayCard(this);
	public final Command<PlayerLost.Options, PlayerLost.Result> _playerLost = new PlayerLost(this);
	
	public final PhaseEvent _unTapPhase= new PhaseEvent(Phase.UnTap,_changePhase);
	public final PhaseEvent _upKeepPhase= new PhaseEvent(Phase.Upkeep,_changePhase);
	public final PhaseEvent _drawPhase = new PhaseEvent(Phase.Draw,_changePhase);
	public final PhaseEvent _main1Phase= new PhaseEvent(Phase.Main1,_changePhase);
	public final PhaseEvent _combatPhase= new PhaseEvent(Phase.Combat,_changePhase);
	public final PhaseEvent _main2Phase= new PhaseEvent(Phase.Main2,_changePhase);
	
	public CommandRepositoryImpl(Game g) {
		_game = g;
	}
	public Command<ChangePhase.Options, ChangePhase.Result> changePhase() {
		return _changePhase;
	}
	
	public ChangePhase.Result changePhase(ChangePhase.Options options) {
		return exec(_changePhase,options);
	}
	public Command<ChangeTurn.Options, ChangeTurn.Result> changeTurn(){
		return _changeTurn;
	}
	public ChangeTurn.Result changeTurn(ChangeTurn.Options options) {
		return exec(_changeTurn,options);
	}
	public PhaseEvent combatPhase() {
		return _combatPhase;
	}
	public Command<Draw.Options, Draw.Result> draw() {
		return _draw;
	}
	public Draw.Result draw(Draw.Options options) {
		return exec(_draw,options);
	}
	public PhaseEvent drawPhase() {
		return _drawPhase;
	}
	public Command<EndGame.Options, EndGame.Result> endGame() {
		return _endGame;
	}
	public EndGame.Result endGame(EndGame.Options options) {
		return exec(_endGame,options);
	}
	private <O,R> R exec(Command<O,R> cmd, O opt){
		return _game.getGameState().do_(cmd, opt);
	}
	public PhaseEvent main1Phase() {
		return _main1Phase;
	}
	public PhaseEvent main2Phase() {
		return _main2Phase;
	}
	public Command<MoveCard.Options, MoveCard.Result> moveCard() {
		return _moveCard;
	}	

	public MoveCard.Result moveCard(MoveCard.Options options) {
		return exec(_moveCard,options);
	}
	public Command<PlayCard.Options, PlayCard.Result> playCard() {
		return _playCard;
	}
	public PlayCard.Result playCard(PlayCard.Options options) {
		return exec(_playCard,options);
	}
	public Command<PlayerLost.Options, PlayerLost.Result> playerLost() {
		return _playerLost;
	}
	public PlayerLost.Result playerLost(PlayerLost.Options options) {
		return exec(_playerLost,options);
	}
	public ActionOptionPair<?>[] requestPlayerActions(PlayerID pid) {
		return _game.requestPlayerAction(pid);
	}

	public PhaseEvent unTapPhase() {
		return _unTapPhase;
	}
	public PhaseEvent upKeepPhase() {
		return _upKeepPhase;
	}
	
}
